package com.telecom.util;

import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//解析xml文件，读取里面的配置信息
@Slf4j(topic = "c.XMLParser")
public class XMLParser {
    //把SqlMapConfig.xml文件传进去，读取，返回一个DbProfile类，将所有配置信息封装到DbProfile类中
    public static DbProfile parseXml(InputStream in) throws Exception {
        DbProfile dbProfile = new DbProfile();
        //使用dom4j解析xml文件
        SAXReader  reader = new SAXReader();
        Document document = reader.read(in);
        //获取到根元素
        Element root=document.getRootElement();
        //从xml中查找所有property节点
        List<Element> list = root.selectNodes("//property");
        for (Element element : list) {
            log.debug("获取到节点:"+element.getName());
            //如果元素name的值是driver，就将value值赋给DbProfile的driver属性
            if (element.attributeValue("name").equals("driver")){
                dbProfile.setDriver(element.attributeValue("value"));
            }
            if (element.attributeValue("name").equals("url")){
                dbProfile.setUrl(element.attributeValue("value"));
            }
            if (element.attributeValue("name").equals("username")){
                dbProfile.setUsername(element.attributeValue("value"));
            }
            if (element.attributeValue("name").equals("password")){
                dbProfile.setPassword(element.attributeValue("value"));
            }
        }
        //读取mappers资源
        List<Element> mapperList = root.selectNodes("//mappers/mapper");
        for (Element element : mapperList) {
            String path=element.attributeValue("resource");
            //通过mapper.xml文件的路径，读取StudentMapper.xml文件，解析StudentMapper.xml文件里的内容
            if (path != null){
                System.out.println(path);
                Map<String,Mapper> mappers=parseMapper(path);
                dbProfile.setMappers(mappers);
            }else{
                String daoPath=element.attributeValue("class");
                Map<String,Mapper> mappers=parseAnnotationDao(daoPath);
                dbProfile.setMappers(mappers);
            }
        }
        return dbProfile;
    }

    private static Map<String,Mapper> parseAnnotationDao(String daoPath) throws ClassNotFoundException {
        log.debug("run with annotation");
        Map<String,Mapper> mappers=new HashMap<>();
        //com.telecom.mapper.StudentDao
        Class<?> aClass = Class.forName(daoPath);
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            boolean b = method.isAnnotationPresent(Select.class);
            if (b) {
                Select annotation = method.getAnnotation(Select.class);
                String sql = annotation.value();
                Mapper mapper = new Mapper();
                mapper.setSqlStatement(sql);
                //方法返回Type对象，方法返回值类型
                Type type = method.getGenericReturnType();
                //当前返回的类型是参数化类型(带有泛型)
                if (type instanceof ParameterizedType){
                    ParameterizedType parameterizedType = (ParameterizedType) type;
                    Type[] types = parameterizedType.getActualTypeArguments();
                    Class entityClass = (Class)types[0];
                    mapper.setClassName(entityClass.getName());
                }
                String methodName = method.getName();
                String className=  method.getDeclaringClass().getName();
                String key=className+"."+methodName;
                mappers.put(key,mapper);
            }
        }
        return mappers;
    }

    private static Map<String,Mapper> parseMapper(String path) throws Exception {//com/telecom/mapper/StudentMapper.xml
        Map<String,Mapper> mappers=new HashMap<>();
        SAXReader reader=new SAXReader();
        InputStream in = Resources.getResourceAsStream(path);
        Document document=reader.read(in);
        //拿到StudentMapper的根元素
        Element rootElement=document.getRootElement();
        //读取命名空间 com.telecom.mapper.StudentMapper
        String namespace=rootElement.attributeValue("namespace");
        List<Element> list = rootElement.selectNodes("//select");
        for (Element element : list) {
            String id=element.attributeValue("id");  //获取id
            String resultType=element.attributeValue("resultType"); //获取返回值类型
            String sqlStatement=element.getText().trim(); //获取SQL语句
            Mapper mapper=new Mapper();
            mapper.setSqlStatement(sqlStatement).setClassName(resultType);
            String key=namespace+"."+id;
            mappers.put(key,mapper);
        }
        return mappers;
    }
}
